/** 
 * @author Huang RuiGuang
 * @date 2008/12/1
 *
 * Herm library
 * Copyright (c) 2008 by Huang RuiGuang(daemon.huang@gmail.com)
 *
 * Permission to use, copy, modify, distribute and sell this software.
 */

#ifndef HERM_FRAMEWORK_UDP_PEER_H
#define HERM_FRAMEWORK_UDP_PEER_H

#include "herm/base/socket/socket_handler.h"
#include "herm/base/network/interface.h"
#include "herm/base/network/common_handler.h"
#include "herm/base/network/udp_session_mgr.h"

namespace herm{
	class Multiplexor;
    class Datagram;
}
class UDPSession;
// class UDPSessionMgr;
class UDPPeer : public herm::IPeer,
			    public herm::ISockHandler,
				private CommonHandler
{
public:
	UDPPeer();
	~UDPPeer(void);

	const herm::Address& GetLocalAddr() const;
	void Reset(herm::Multiplexor* multiplexor, herm::IListener* listener, 
		const herm::UDPeerParam& peerParam);
	void Reset(const herm::Address& addr, herm::Multiplexor* multiplexor, 
		herm::IListener* listener, const herm::UDPeerParam& peerParam);

	inline int GetErrType() const
	{
		return m_state;
	}	

	UDPSession* AcceptSessions();
	/**
	 * @brief get the current session.
	 * @param [session] save the current session.
	 * @return if the receiving queue is empty, return false; else true.
	 */
	 bool GetCurSession(UDPSession*& session);
	/**
	 * @brief Get the first session in receiving buffer.
	 */
	UDPSession* GetSession(const herm::Address& addr);
	UDPSessionObjMgr* GetSessions() const;
	int Fetch(char* buf, int& len);
	int Push(const char* buf, int len, const herm::Address& addr);
private: 
	// IEventHandler virtual functions
	virtual herm::Handle OnGetHandle() const;
	/**
	* @brief, receive data from socket and write to receiving queue.
	*/
	virtual int OnReceive(int);
	virtual int OnSend(int);
	virtual void OnError(int stateType, int stateCode);

	// herm::IPeer virtual
	virtual herm::ISession* CreateSession(const std::string& servName, 
		const herm::Address& remoteAddr, bool isReconnect, bool isBlock, 
		herm::INBCNotifier* notifier);
	virtual herm::ISession* GetSession(int) { return nullptr; }
	virtual void DestroySession(int sessinIdx);
	virtual void Finish();

	virtual herm::IListener* GetListener() const;

	void CommonReset(herm::Multiplexor* multiplexor, herm::IListener* listener, 
		const herm::UDPeerParam& peerParam);
	void DropData();

public:
	herm::UDPeerParam m_peerParam;
private:
	herm::Multiplexor* m_multiplexor;
	herm::IListener* m_listener;
	herm::Datagram* m_datagram;
	herm::Address m_localAddr;
	herm::Buffer* m_recvBuffer;
	herm::Buffer* m_sendBuffer;
	herm::uint32_t m_state; // state type&code
	bool m_removed;
	volatile bool m_enableWrite;
	UDPSessionMgr* m_dsMgr;
	herm::Address m_newAddr;
	char* m_tmpBuf;
};

#endif
